﻿using Language;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.Windows.Forms.DataVisualization.Charting;

namespace LargeSquareOne
{
    public partial class FrmCpkCount : MultiLanguageForm
    {
        public FrmCpkCount()
        {
            InitializeComponent();
        }
        #region 减少闪烁
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x02000000;
                return cp;
            }
        }
        #endregion



        private void FrmCpkCount_Load(object sender, EventArgs e)
        {

        }

        private void btn_Add_Click(object sender, EventArgs e)
        {

            List<double> data = GetSPCData();
            // 计算Xbar和R
            double xbar = CalculateXbar(data);
            double r = CalculateR(data);

            // 计算控制限
            double uclXbar = CalculateUCLXbar(data.Count);
            double lclXbar = CalculateLCLXbar(data.Count);
            double uclR = CalculateUCLR(data.Count);
            double lclR = CalculateLCLR(data.Count);


            // 清空图表
            chartControl.Series.Clear();
            double xmaxValue = Math.Max(xbar, Math.Max(uclXbar, uclR));
            double xminValue = Math.Max(xbar, Math.Max(lclXbar, lclR));

            chartControl.ChartAreas[0].AxisY.Maximum = xmaxValue + 2;
            chartControl.ChartAreas[0].AxisY.Minimum = xminValue + 2;

            //double rmaxValue = Math.Max(r, uclR);
            //double rminValue = Math.Max(r, lclR);

            //chartControl.ChartAreas[1].AxisY.Maximum = rmaxValue;
            //chartControl.ChartAreas[1].AxisY.Minimum = rminValue;

            // 绘制Xbar-R控制图
            Series seriesXbar = new Series();
            seriesXbar.ChartType = SeriesChartType.Line;
            seriesXbar.Name = "Xbar";

            Series seriesR = new Series();
            seriesR.ChartType = SeriesChartType.Line;
            seriesR.Name = "R";


            // 添加数据点和控制限
            chartControl.Series.Add(seriesXbar);
            chartControl.Series.Add(seriesR);


            for (int i = 0; i < data.Count; i++)
            {
                seriesXbar.Points.AddXY(i + 1, xbar);
                seriesR.Points.AddXY(i + 1, r);
            }


        }


        // 假设这是获取SPC数据的方法
        private List<double> GetSPCData()
        {
            // 返回样本数据的List<double>
            // 根据需要修改为实际的获取方法
            return new List<double> { 1.2, 1.3, 1.0, 2.5, 2.2, 2.8, 0.8, 0.9, 1.1 };
        }

        /// <summary>
        /// 对样本进行分组
        /// </summary>
        /// <param name="sampleData"></param>
        /// <param name="groupSize"></param>
        /// <returns></returns>
        private List<List<double>> groupedData(List<double> sampleData, int groupSize = 3)
        {
            List<List<double>> groupedData = new List<List<double>>();

            for (int i = 0; i < sampleData.Count; i += groupSize)
            {
                List<double> group = sampleData.Skip(i).Take(groupSize).ToList();
                groupedData.Add(group);
            }
            return groupedData;
        }



        // 假设这是计算Xbar的方法
        private double CalculateXbar(List<double> data)
        {
            // 根据输入的样本数据计算Xbar
            // 根据需要修改为实际的计算方法
            double sum = 0;
            foreach (var value in data)
            {
                sum += value;
            }
            return sum / data.Count;
        }

        // 假设这是计算R的方法
        private double CalculateR(List<double> data)
        {
            // 根据输入的样本数据计算R
            // 根据需要修改为实际的计算方法
            double max = data[0];
            double min = data[0];

            foreach (var value in data)
            {
                if (value > max)
                    max = value;
                if (value < min)
                    min = value;
            }
            return max - min;
        }

        #region 根据样本大小计算UCL(Xbar)
        // 这是计算UCL(Xbar)的方法
        private double CalculateUCLXbar(int sampleSize)
        {
            // 根据样本大小计算UCL(Xbar)
            // 根据需要修改为实际的计算方法
            double Xbar_bar = 0; // 所有样本均值的平均值
            double R_bar = 0; // 所有样本范围的平均值
            double A2 = 0; // 控制系数

            // 根据样本大小确定控制系数A2
            if (sampleSize <= 25)
            {
                A2 = 0.577;
            }
            else if (sampleSize <= 100)
            {
                A2 = 0.425;
            }
            else if (sampleSize <= 500)
            {
                A2 = 0.372;
            }
            else
            {
                // 根据需要添加更多样本大小的控制系数A2
            }


            //对样本进行分组
            List<double> data = GetSPCData();

            // 计算每个样本的均值和范围
            List<double> sampleMeans = CalculateSampleMeans(groupedData(data));
            List<double> sampleRanges = CalculateSampleRanges(groupedData(data));

            // 计算所有样本均值的平均值和所有样本范围的平均值
            Xbar_bar = sampleMeans.Average();
            R_bar = sampleRanges.Average();

            // 计算UCL(Xbar)
            double UCL_Xbar = Xbar_bar + (A2 * R_bar);

            return UCL_Xbar;
        }

        // 根据需要实现计算样本均值的方法
        private List<double> CalculateSampleMeans(List<List<double>> sampleData)
        {
            // 根据样本数据计算每个样本的均值，并返回一个包含所有样本均值的List<double>
            // 根据实际的计算方法进行修改
            List<double> sampleMeans = new List<double>();

            foreach (var sample in sampleData)
            {
                double sum = 0;
                int count = sample.Count;

                foreach (var value in sample)
                {
                    sum += value;
                }

                double mean = sum / count;
                sampleMeans.Add(mean);
            }

            return sampleMeans;
        }

        // 根据需要实现计算样本范围的方法
        private List<double> CalculateSampleRanges(List<List<double>> sampleData)
        {
            // 根据样本数据计算每个样本的范围，并返回一个包含所有样本范围的List<double>
            // 根据实际的计算方法进行修改
            List<double> sampleRanges = new List<double>();

            foreach (var sample in sampleData)
            {
                double min = sample.Min();
                double max = sample.Max();
                double range = max - min;
                sampleRanges.Add(range);
            }

            return sampleRanges;
        }
        #endregion

        #region 计算LCL(Xbar)的方法
        private double CalculateLCLXbar(int sampleSize)
        {
            // 根据样本大小计算LCL(Xbar)
            // 根据需要修改为实际的计算方法

            double Xbar_bar = 0; // 所有样本均值的平均值
            double R_bar = 0; // 所有样本范围的平均值
            double A2 = 0; // 控制系数

            // 根据样本大小确定控制系数A2
            if (sampleSize <= 25)
            {
                A2 = 0.577;
            }
            else if (sampleSize <= 100)
            {
                A2 = 0.425;
            }
            else if (sampleSize <= 500)
            {
                A2 = 0.372;
            }
            else
            {
                // 根据需要添加更多样本大小的控制系数A2
            }

            //对样本进行分组
            List<double> data = GetSPCData();

            // 计算每个样本的均值和范围
            List<double> sampleMeans = CalculateSampleMeans(groupedData(data));
            List<double> sampleRanges = CalculateSampleRanges(groupedData(data));

            // 计算所有样本均值的平均值和所有样本范围的平均值
            Xbar_bar = sampleMeans.Average();
            R_bar = sampleRanges.Average();

            // 计算LCL(Xbar)
            double LCL_Xbar = Xbar_bar - (A2 * R_bar);

            return LCL_Xbar;
        }

        /// <summary>
        /// 根据样本大小选择合适的A2值
        /// </summary>
        /// <param name="sampleSize"></param>
        /// <returns></returns>
        private double GetA2(int sampleSize)
        {
            double A2 = 0; // 控制系数

            // 
            if (sampleSize == 2)
            {
                A2 = 1.880;
            }
            else if (sampleSize == 3)
            {
                A2 = 1.023;
            }
            else if (sampleSize == 4)
            {
                A2 = 0.729;
            }
            else if (sampleSize == 5)
            {
                A2 = 0.577;
            }
            else if (sampleSize == 6)
            {
                A2 = 0.483;
            }
            else if (sampleSize > 6)
            {
                A2 = 3 / Math.Sqrt(sampleSize);
            }
            else
            {
                // 根据需要添加更多样本大小的A2值
            }

            return A2;
        }
        #endregion

        #region 计算UCL(R)的方法
        // 假设这是计算UCL(R)的方法
        private double CalculateUCLR(int sampleSize)
        {
            // 根据样本大小计算UCL(R)
            // 根据需要修改为实际的计算方法
            double R_bar = 0; // 所有样本范围的平均值
            double D4 = 0; // 控制系数

            // 根据样本大小确定控制系数D4
            D4 = GetD4(sampleSize);

            //对样本进行分组
            List<double> data = GetSPCData();
            // 计算每个样本的范围
            List<double> sampleRanges = CalculateSampleRanges(groupedData(data));

            // 计算所有样本范围的平均值
            R_bar = sampleRanges.Average();

            // 计算UCL(R)
            double UCL_R = D4 * R_bar;

            return UCL_R;
        }


        #region  控制系数D4计算

        //如果样本大小大于或等于2，但小于等于8，那么D4的值为2.282。
        //如果样本大小大于8，但小于等于10，那么D4的值为2.115。
        //如果样本大小大于10，但小于等于15，那么D4的值为2.004。
        //如果样本大小大于15，但小于等于20，那么D4的值为1.924。
        //如果样本大小大于20，但小于等于25，那么D4的值为1.864。
        //如果样本大小大于25，但小于等于30，那么D4的值为1.816。
        //对于更大的样本大小，您可以在SPC的相关文献或标准表中查找合适的D4的值。
        private double GetD4(int sampleSize)
        {
            double D4 = 0; // 控制系数

            // 根据样本大小选择合适的D4值
            if (sampleSize >= 2 && sampleSize <= 8)
            {
                D4 = 2.282;
            }
            else if (sampleSize > 8 && sampleSize <= 10)
            {
                D4 = 2.115;
            }
            else if (sampleSize > 10 && sampleSize <= 15)
            {
                D4 = 2.004;
            }
            else if (sampleSize > 15 && sampleSize <= 20)
            {
                D4 = 1.924;
            }
            else if (sampleSize > 20 && sampleSize <= 25)
            {
                D4 = 1.864;
            }
            else if (sampleSize > 25 && sampleSize <= 30)
            {
                D4 = 1.816;
            }
            else
            {
                // 对于更大的样本大小，根据需要添加更多D4的值
            }

            return D4;
        }
        #endregion

        #endregion

        #region 计算LCL(R)的方法
        private double CalculateLCLR(int sampleSize)
        {
            // 根据样本大小计算LCL(R)
            // 根据需要修改为实际的计算方法
            double R_bar = 0; // 所有样本范围的平均值
            double D3 = 0; // 控制系数

            // 根据样本大小确定控制系数D3
            D3 = GetD3(sampleSize);

            //对样本进行分组
            List<double> data = GetSPCData();
            // 计算每个样本的范围
            List<double> sampleRanges = CalculateSampleRanges(groupedData(data));

            // 计算所有样本范围的平均值
            R_bar = sampleRanges.Average();

            // 计算LCL(R)
            double LCL_R = D3 * R_bar;

            return LCL_R;
        }

        /// <summary>
        /// 根据样本大小选择合适的D3值
        /// </summary>
        /// <param name="sampleSize"></param>
        /// <returns></returns>
        /// 
        ///如果样本大小大于或等于2，但小于等于6，那么D3的值为0。
        //如果样本大小为7，那么D3的值为0。
        //如果样本大小大于7，但小于等于8，那么D3的值为0.076。
        //如果样本大小大于8，但小于等于10，那么D3的值为0.136。
        //如果样本大小大于10，但小于等于12，那么D3的值为0.184。
        //如果样本大小大于12，但小于等于16，那么D3的值为0.223。
        //如果样本大小大于16，但小于等于20，那么D3的值为0.251。
        //如果样本大小大于20，但小于等于25，那么D3的值为0.277。
        //对于更大的样本大小，您可以在SPC的相关文献或标准表中查找合适的D3的值。
        private double GetD3(int sampleSize)
        {
            double D3 = 0; // 控制系数
            if (sampleSize >= 2 && sampleSize <= 6)
            {
                D3 = 0;
            }
            else if (sampleSize == 7)
            {
                D3 = 0;
            }
            else if (sampleSize > 7 && sampleSize <= 8)
            {
                D3 = 0.076;
            }
            else if (sampleSize > 8 && sampleSize <= 10)
            {
                D3 = 0.136;
            }
            else if (sampleSize > 10 && sampleSize <= 12)
            {
                D3 = 0.184;
            }
            else if (sampleSize > 12 && sampleSize <= 16)
            {
                D3 = 0.223;
            }
            else if (sampleSize > 16 && sampleSize <= 20)
            {
                D3 = 0.251;
            }
            else if (sampleSize > 20 && sampleSize <= 25)
            {
                D3 = 0.277;
            }
            else
            {
                // 对于更大的样本大小，根据需要添加更多D3的值
            }

            return D3;
        }
        #endregion
    }
}
